package com.taotao.config;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.taotao.config.service.ConfigClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 余胜军
 * @ClassName StartReadConfiguration
 * @qq 644064779
 * @addres www.mayikt.com
 * 微信:yushengjun644
 */
public class StartReadConfiguration implements EnvironmentAware, ApplicationListener<ContextRefreshedEvent> {
    private StandardEnvironment environment;
    private MayiktBeanDefinitionRegistry mayiktBeanDefinitionRegistry;
    private BeanDefinitionRegistry beanDefinitionRegistry;
    @Autowired
    private ConfigurableApplicationContext applicationContext;
    @Autowired
    private ConfigClientService configClientService;
    private ScheduledExecutorService scheduledService = Executors.newSingleThreadScheduledExecutor();

    public void init() {
        mayiktBeanDefinitionRegistry = (MayiktBeanDefinitionRegistry)
                applicationContext.getBeanFactory().getBean("mayiktBeanDefinitionRegistry");
        beanDefinitionRegistry = mayiktBeanDefinitionRegistry.getBeanDefinitionRegistry();
        MutablePropertySources propertySources = environment.getPropertySources();
        propertySources.forEach(propertySource -> {
            if (propertySource instanceof OriginTrackedMapPropertySource) {
                OriginTrackedMapPropertySource originTrackedMapPropertySource
                        = (org.springframework.boot.env.OriginTrackedMapPropertySource) propertySource;
                JSONObject configInfo = configClientService.rpcHttpGetConfig();
                if (configInfo == null) {
                    return;
                }
                Map map = new HashMap();
                map.putAll(originTrackedMapPropertySource.getSource());
                JSONArray config = configInfo.getJSONArray("config");
                for (int i = 0; i < config.size(); i++) {
                    JSONObject jsonObject = config.getJSONObject(i);
                    String key = jsonObject.getString("key");
                    String value = jsonObject.getString("value");
                    originTrackedMapPropertySource.getSource().put(key, value);
                    System.out.println(originTrackedMapPropertySource.getSource().toString() + "****");
                    map.put(key, value);
                }
                System.out.println(map.toString() + "&&&&&&&&&&&&");
                originTrackedMapPropertySource.getSource().putAll(map);
                String md5 = configInfo.getString("md5");
                refreshBean();// 刷新配置

                // 开启定时任务检查配置文件是否有发生变化
                scheduledService.scheduleAtFixedRate(new CheckConfigurationFileThread(), 3, 3, TimeUnit.SECONDS);
            }
        });

    }


    @Override
    public void setEnvironment(Environment environment) {
        this.environment = (StandardEnvironment) environment;
    }

    private void refreshBean() {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanDefinitionName);
            if ("mayiktRefresh".equals(beanDefinition.getScope())) {
                applicationContext.getBeanFactory().destroyBean(beanDefinitionName);
                // 卸载该bean
                RefreshScope.getBeans().remove(beanDefinitionName);
                Object bean = applicationContext.getBean(beanDefinitionName);
            }
        }
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        init();
    }

    class CheckConfigurationFileThread implements Runnable {

        @Override
        public void run() {
            JSONObject result = configClientService.md5Comparison();
            Integer code = result.getInteger("code");
            if (code != 201) {
                return;
            }
            JSONObject data = result.getJSONObject("data");
            MutablePropertySources propertySources = environment.getPropertySources();
            propertySources.forEach(propertySource -> {
                if (propertySource instanceof OriginTrackedMapPropertySource) {
                    OriginTrackedMapPropertySource originTrackedMapPropertySource
                            = (org.springframework.boot.env.OriginTrackedMapPropertySource) propertySource;
                    JSONObject configInfo = configClientService.rpcHttpGetConfig();
                    if (configInfo == null) {
                        return;
                    }
                    JSONArray config = configInfo.getJSONArray("config");
                    for (int i = 0; i < config.size(); i++) {
                        JSONObject jsonObject = config.getJSONObject(i);
                        String key = jsonObject.getString("key");
                        String value = jsonObject.getString("value");
                        originTrackedMapPropertySource.getSource().put(key, value);
                    }
                    refreshBean();// 刷新配置
                    ConfigMd5.setMd5(result.getJSONObject("data").getString("md5"));
                }
            });
        }
    }
}
